import viz
import viztask
import time
import math
import projector

from time import time
from Action import *
from Gui import *
from VizSoundAction import *
from SimonButton import *

class Game:
	
	def __init__(self):
		self.simonActionStack = Action() #The correct sequence of actions, determined by simon
		self.myActionStack = Action() #The current sequence of actions that the user has inputed
		self.vrsimon = viz.add('resources/base.dae',pos=[0,0,0])	#place the VRSimon base
		self.collision = False
		self.permissions = 'n'
		self.outputFile = None
		self.backgroundMusic  = viz.addAudio('resources/sounds/DepressedTreatment.mp3')
		self.backgroundMusic.loop( viz.ON )
		self.backgroundMusic.volume(.3)
		self.backgroundMusic.play()
		
		self.offset = [0,0.6,-0.33]
		self.range = [0,0.6,-0.33]
		self.scale = 250
		
	
	def showSequence(self): #Shows simons sequence of actions
		if(self.permissions == 'w'):
			self.recordNextSequence()
		speed = 0.25
		if(len(self.simonActionStack.actionStack) > 5):
			speed -= 0.05
		if(len(self.simonActionStack.actionStack) > 10):
			speed -= 0.05
		if(len(self.simonActionStack.actionStack) > 15):
			speed -= 0.05
		
		self.vrsimon.addAction(vizact.waittime(1))
		self.signal = vizact.signal()
		self.vrsimon.addAction(self.signal.trigger)
		i = 0

		for action in self.simonActionStack.actionStack:
			for button in buttons:
				if button.getNum() == action:
					button.blink(speed)
			
	def addAction(self, action):
		self.myActionStack.addAction(action)
		if self.simonActionStack.compareActions(self.myActionStack) != True:
			self.myActionStack.clearActions()
			self.simonActionStack.clearActions()
			return 0
		elif len(self.simonActionStack.actionStack) == len(self.myActionStack.actionStack):
			self.myActionStack.clearActions()
			if(self.permissions == 'w'):
				self.simonActionStack.addRandomAction()
			return 2
		else:
			return 1
	
	
	def delayCollision(self):
		yield viztask.waitTime(0.8)
		self.collision = False;
	
	def setCollision(self):
		self.collision = True;
		viztask.schedule(self.delayCollision())
		
	def replay(self):
		try:
			line = self.outputFile.readline()
			if(str.find(line, "NEXTSEQUENCE") != -1):
				nextSequence = eval(str.replace(line, "NEXTSEQUENCE ", ""))
				self.simonActionStack.setActionStack(nextSequence)
				self.showSequence()
			else:
				pos = eval(line)
				handShadow.setPosition(pos[0], pos[1], pos[2], viz.ABS_GLOBAL)
		except SyntaxError:
			return

	def getNextSequence(self):
		try:
			self.simonActionStack.setActionStack(eval(outputFile.readline()))
		except SyntaxError:
			return
			
	def recordPosition(self):
		self.outputFile.write(str(handShadow.getPosition()) + "\n")
		return
		
	def recordNextSequence(self):
		self.outputFile.write("NEXTSEQUENCE " + str(game.simonActionStack.actionStack) + "\n")
		return


####Kinect Input##################################

def kinectInput():
	if(game.permissions == 'r'):
		game.replay()
		return
	kinectHandPosition = handTracker.getPosition()
	if kinectHandPosition[0] == 0:
		kinectHandPosition = secondaryHandTracker.getPosition()
	kinectHandPosition[0] -= game.offset[0]
	kinectHandPosition[1] -= game.offset[1]
	kinectHandPosition[2] -= game.offset[2]

	calibratedHandPosition = [0,0,0]
	
	calibratedHandPosition[0] = -kinectHandPosition[2]*game.scale + 60 #Front/Back
	calibratedHandPosition[1] = kinectHandPosition[1]*game.scale + 75 #Up/Down
	calibratedHandPosition[2] = kinectHandPosition[0]*game.scale + 60 #Left/Right
	
	handShadow.setPosition(calibratedHandPosition, viz.ABS_GLOBAL)
	
	if(game.permissions == 'w'):
		game.recordPosition()
		return

vrpn = viz.add('vrpn7.dle')
handTracker = vrpn.addTracker('Tracker0@localhost', 14)
secondaryHandTracker = vrpn.addTracker('Tracker0@localhost', 8)
vizact.ontimer(0.025,kinectInput)
##################################################



####Keyboard Input################################
def onKeyDown(key):
	if key == viz.KEY_RETURN:
		game.offset = handTracker.getPosition()
		if game.offset[0] == 0:
			game.offset = secondaryHandTracker.getPosition()
	elif key == ' ':
		game.range = handTracker.getPosition()
		game.scale = 60 / ( game.offset[0] - game.range[0] )
		print game.scale
	elif key == 'r':
		game.scale = 250
viz.callback(viz.KEYDOWN_EVENT,onKeyDown)


def keyboardInput():
	global collisionObj
	if(game.permissions == 'r'):
		game.replay()
		return
	
	if(viz.key.isDown(viz.KEY_LEFT)):
			handShadow.setPosition(0, 0, 1, viz.REL_PARENT)
	if(viz.key.isDown(viz.KEY_DOWN)):
			handShadow.setPosition(-1, 0, 0, viz.REL_PARENT)
	if(viz.key.isDown(viz.KEY_RIGHT)):
			handShadow.setPosition(0, 0, -1, viz.REL_PARENT)
	if(viz.key.isDown(viz.KEY_UP)):
			handShadow.setPosition(1, 0, 0, viz.REL_PARENT)
	if(viz.key.isDown('d')):
			handShadow.setPosition(0, -1, 0, viz.REL_PARENT)
	if(viz.key.isDown('a')):
			handShadow.setPosition(0, 1, 0, viz.REL_PARENT)
	if(game.permissions == 'w'):
		game.recordPosition()
		return

#vizact.ontimer(0.025,keyboardInput)
##################################################



####Collisions####################################
def onCollideBegin(collision):
	if game.collision == True:
		return
		
	game.setCollision()
	for button in buttons:
		if button.vizObject == collision.obj2:
			pressResult = button.press()
			if pressResult == 1:
				pass
			elif pressResult == 2:
				if(game.permissions == 'w'):
					game.showSequence()
			else:
				game.permissions = 'n'
				game.outputFile.close()
				game.outputFile = None

viz.phys.enable()
viz.phys.setGravity(0,0,0)
viz.collision( viz.ON )
viz.MainView.collision(viz.OFF)
viz.callback( viz.COLLIDE_BEGIN_EVENT, onCollideBegin)
##################################################



####Graphicss Settings############################
def GenerateStarDome(numStars, pointSize, minRadius, maxRadius):
	#Create a star dome of random points
	viz.startlayer(viz.POINTS)
	viz.pointsize(pointSize)
	for i in range(0, numStars):
		x = random.random() - 0.5
		y = random.random() - 0.5
		z = random.random() - 0.5
		length = math.sqrt(x*x + y*y + z*z)
		rad = vizmat.GetRandom(minRadius*1,maxRadius*1)
		x = x / length * rad
		y = y / length * rad
		z = z / length * rad
		color = vizmat.GetRandom(0.4,1)
		viz.vertexcolor(color,color,color-vizmat.GetRandom(0,0.2))
		viz.vertex(x, y, z)
	
	stardome = viz.endlayer()
	stardome.texture( viz.add('particle.rgb') )
	stardome.blendFunc(viz.GL_SRC_ALPHA,viz.GL_DST_ALPHA)
	stardome.enable(viz.POINT_SPRITE)
	stardome.disable(viz.DEPTH_TEST)
	stardome.draworder(-10)
	stardome.setScale([100]*3)

GenerateStarDome(2000,2,50,100)
GenerateStarDome(2000,4,50,100)
GenerateStarDome(1000,6,50,100)
viz.setOption("viz.antialias", "4")
viz.clearcolor(0,0.05,0.1) 				
viz.mouse(viz.OFF)  						

light = viz.addLight()
light.position(0,0,0)
light.enable()
##################################################



####Camera########################################
viz.MainView.move(-100,160,60)
viz.MainView.lookat( [10,60,60] )
##################################################



####Game##########################################
viz.setOption('viz.fullscreen', '1')
viz.go()
game = Game()
gui = Gui(vizact, game)
##################################################



####Button########################################
buttons = []

buttons.append(SimonButton(vizact, game, 'resources/r.dae',[4,19,63], "red"))
buttons.append(SimonButton(vizact, game, 'resources/g.dae',[62,19,63], "green"))
buttons.append(SimonButton(vizact, game, 'resources/b.dae',[4,19,5], "blue"))
buttons.append(SimonButton(vizact, game, 'resources/y.dae',[62,19,5], "yellow"))
##################################################



####Hand##########################################
handShadow = projector.add( viz.add('resources/shadow.jpg') )
handShadow.setPosition(60, 75, 60, viz.ABS_GLOBAL)
handShadow.setEuler(0, 90, 0)
handShadow.enable(viz.COLLIDE_NOTIFY)
handShadow.disable(viz.DYNAMICS)
handShadow.setScale([0.60]*3)
handShadow.ortho(1, 1)

hand = handShadow.add('resources/arm.dae')
hand.setEuler(140, 0, -90)
hand.setPosition(-125, -75, 260, viz.REL_PARENT)
hand.alpha(1)

handShadow.collideMesh()
for button in buttons:
	handShadow.affect(button.vizObject)

handShadow.affect(game.vrsimon)
##################################################